DragCallbacks就像各種AndroidNative原生開發時用來處理點擊或觸碰的Listener一樣,只是它叫做「callback」。
(真的不懂很多人、或很多文章喜歡煞有其事的解釋和定義「Listener」與「callback」的不同。)
一個FlameGame可以擴充一個DragCallbacks
class MyGame extends flame.FlameGame with DragCallbacks{
@override
void onDragUpdate(DragUpdateEvent event) {
super.onDragUpdate(event);
}
}
比較奇妙的地方是按照Flutter的特性,DragCallbacks不單單只是個接口(interface),而是有自己完整的物件特性,——它自己也是繼承自Component。
(這裡會有些有趣的假想,晚點、或過幾天來測試。)
但什麼是Component?
如果Flutter中,所有東西都是Widget,那Flame中所有東西都是Component。——除了FlameGame本身以外吧!
遊戲選單是Component,遊戲角色是個COmponent,遊戲怪物是個COmponent,遊戲中一顆子彈也「可以」是個Component。
所有東西都是Component。
而Component跟FlameGame一樣也有「update」與「render」。
例如...
class FlowerComponent extends PositionComponent with DragCallbacks {
@override
void render(Canvas canvas) {
super.render(canvas);
flowerPainter.paint(canvas, Size(size.x, size.y));
}
@override
void update(double dt) {
super.update(dt);
newIndex += dt*33.333;
flowerPainter.setIndex( (newIndex.toInt()%30));
}
}
這是個利用Component畫花、而不在FlameGame中畫的方法。
FlameGame有個「add」函數,可以將「Component」跟FlameGame連結起來,則FlameGame運行時,自然會去呼叫它所有的Component內的「update」與「render」。
(比較奇妙的是:Component內的render時使用的座標完全是以自己的左上角為(0,0),不會被這個Component在整個FlameGame中的座標所影響。這大大降低了設計render的難度....或事實上反而增加了?)
@override
Future<void> onLoad() async {
square = FlowerComponent();
square.width = 80;
square.height = 80;
add(square);
}
可以看到這段範例中有「幫Component設定大小」的程式碼。
就跟許多Widget一樣,Component必須要指定大小給它。(然後這段功能會預設這個Component的座標為(0,0)
。)
回來講DragCallbacks。
結合上一篇的範例,先直接在FlameGame中使用DragCallbacks,然後來拖動花吧!
flame.NotifyingVector2 position = flame.NotifyingVector2(40, 40);
@override
void onDragUpdate(DragUpdateEvent event) {
super.onDragUpdate(event);
position.add(event.localDelta);
flowerPainter.setCenter(position.x, position.y);
}
可以看出來,程式碼必須新增一個參數,用來管理CustomPainter所需要的「座標」,(其實FlowerPainter也做了些修正,例如增加了可以隨時變換座標的「setCenter」,還有繪圖時會使用這個Center座標。)
但操作上真正的問題是:整個遊戲畫面的每一個地方點擊滑動時,花朵都會跟著移動。
也就是說:需要自行判斷玩家是否點擊到了花朵才行,如果沒有點擊到,則「花朵座標變化」的程式碼就不該執行。
(其實這段程式碼不難,只是累了、工作量很大,所以就不做了。)
但如果改用Component來擴充實作DragCallbacks,結果就不一樣了!
@override
void onDragUpdate(DragUpdateEvent event) {
position.add(event.localDelta);
}
這樣就好了!
這樣就能精準的移動花朵!
(但其實不是所有Component擴充實作DragCallbacks後都有這樣的結果,必須要是PositionComponent才行,因為PositionComponent有自帶判斷「是否被點擊」的功能。)
這個簡單的測試跟比較,讓我們知道了「使用Component」的潛在優勢。
因為這個框架並不會限制我們進行設計的方向與限度,還能大幅度簡化我們需要做的事情。